﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using GraphInformation;
using ComplexNetGeneratorLib;
using EpidemicSimulator;
using EpidemicSimulator.stopconditions;
using System.Security.Permissions;
using System.IO;
using System.Reflection;
using QuickGraph;
using QuickGraph.Serialization;
using EpidemicSimulator.states;
using EpidemicSimulator.strategies;
using System.Net;
using System.Globalization;
using EpidemicSimulator.reports;
using NosoiFigthersWeb.db;
using QuickGraphBuilder;
using GraphMLComplexType;
using System.Text;

namespace NosoiFigthersWeb {
	/// <summary>
	/// Summary description for GraphProviderService1
	/// </summary>
	[WebService(Namespace = "http://nosoifigthers.studentlive.pl/")]
	[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
	[System.ComponentModel.ToolboxItem(false)]

	// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
	[System.Web.Script.Services.ScriptService]
	public class GraphProviderService : System.Web.Services.WebService {
		[WebMethod]
		public Graph CreateGraph(String graphML, String stateMachineGraphML, String token, int MaxSimStep) {
			Simulation s = null;
			SimulationSetup simsetup = new SimulationSetup(graphML, stateMachineGraphML, 1, 1);
			s = SimulationFactory.createSimulation(simsetup, HttpContext.Current.Server.MapPath("App_Data"));//HttpContext.Current.Server.MapPath("App_Data/terror.graphml.xml"), HttpContext.Current.Server.MapPath("App_Data/sis.graphml.xml"));
			s.addStopCondition(new MaxSimStepNumberStopCondition(MaxSimStep));
			Application[token.ToString()] = s;

			var g = s.getSimulationResultForSilverlight();

			Application[token] = s;

			Graph resultG = new Graph();
			resultG.Vertices = new GraphElement[g.VertexCount];
			for (int i = 0; i < g.VertexCount; i++) {
				var v = g.Vertices.ElementAt(i);
				resultG.Vertices[i] = v;
			}


			resultG.Edges = new GraphEdge[g.Edges.Count()];
			for (int i = 0; i < g.Edges.Count(); i++) {
				var e = g.Edges.ElementAt(i);
				resultG.Edges[i] = new GraphEdge(e.Source, e.Target);
			}
			// resultG.Height = CountInfectious(s);
			return resultG;
		}

        [WebMethod]
        public Graph CreateGraphFromGraphML(String graphML ){
        
            //string token="12";
            Simulation s = null;
            SimulationSetup simsetup = new SimulationSetup(graphML, null, 1, 1);
            s = SimulationFactory.createSimulation(simsetup, HttpContext.Current.Server.MapPath("App_Data"));//HttpContext.Current.Server.MapPath("App_Data/terror.graphml.xml"), HttpContext.Current.Server.MapPath("App_Data/sis.graphml.xml"));
           
            //Application[token.ToString()] = s;

            var g = s.getSimulationResultForSilverlight();

            //Application[token] = s;

            Graph resultG = new Graph();
            resultG.Vertices = new GraphElement[g.VertexCount];
            for (int i = 0; i < g.VertexCount; i++)
            {
                var v = g.Vertices.ElementAt(i);
                resultG.Vertices[i] = v;
            }


            resultG.Edges = new GraphEdge[g.Edges.Count()];
            for (int i = 0; i < g.Edges.Count(); i++)
            {
                var e = g.Edges.ElementAt(i);
                resultG.Edges[i] = new GraphEdge(e.Source, e.Target);
            }
            // resultG.Height = CountInfectious(s);
            return resultG;
        }

        [WebMethod(EnableSession = true)]
        public int getSimulationMaxTime()
        {
            Simulation s = Context.Session["simulation"] as Simulation;
            foreach (var c in s.stopConditions)
            {
                if (c is MaxSimStepNumberStopCondition)
                    return ((c as MaxSimStepNumberStopCondition)).getMaxSimTimeStepNumberStopCondition();
            }
            return int.MaxValue;
        }



		[WebMethod]
		public Graph CreateDiseaseModelGraph(string modelML) {
			Graph resultG = new Graph();

			var g = new AdjacencyGraph<DiseaseModelNode, DiseaseModelEdge>();
			StringReader reader = new StringReader(modelML);
			try {
				g.DeserializeFromGraphML(
					reader,
					id => new DiseaseModelNode(),
					new IdentifiableEdgeFactory<DiseaseModelNode, DiseaseModelEdge>(SimulationFactory.CreateEdge<DiseaseModelNode, DiseaseModelEdge>)
				);
			}
			catch (Exception e) {
				throw e;
			}
			reader.Close();

			var map = new Dictionary<DiseaseModelNode, GraphElement>();
			resultG.Vertices = new GraphElement[g.VertexCount];
			for (int i = 0; i < g.VertexCount; i++) {
				var v = g.Vertices.ElementAt(i);
				resultG.Vertices[i] = new GraphElement();
				resultG.Vertices[i].Id = i;
				resultG.Vertices[i].Keys.Add(new PairKeyValue("nodeColor", v.nodeColor));
				resultG.Vertices[i].Keys.Add(new PairKeyValue("nodeX", v.nodeX));
				resultG.Vertices[i].Keys.Add(new PairKeyValue("nodeY", v.nodeY));
				resultG.Vertices[i].Keys.Add(new PairKeyValue("stateName", v.stateName));
				map.Add(v, resultG.Vertices[i]);
			}
			resultG.Edges = new GraphEdge[g.Edges.Count()];
			for (int i = 0; i < g.Edges.Count(); i++) {
				var e = g.Edges.ElementAt(i);
				resultG.Edges[i] = new GraphEdge(map[e.Source], map[e.Target]);
			}

			return resultG;
		}

		[WebMethod(EnableSession=true)]
		public Graph StartSimulation(SimulationSetupSL simsetup, String token) {
			Graph resultG = new Graph();

			try {
				Simulation s = null;

				if (simsetup.networkGraph != null) {
					var graph = simsetup.networkGraph.GetGraphFormSilverlight();
				}

                SimulationSetup simulationSetup = new SimulationSetup(simsetup.networkGraphML, simsetup.diseaseModelGraphML, simsetup.maxContactsPerStep, simsetup.minContactsPerStep);
                simulationSetup.condition = simsetup.condition;
                simulationSetup.networkGraph = simsetup.networkGraph;
				simulationSetup.stateChangePlansSL = simsetup.stateChangePlansSL;
				simulationSetup.stopConditionsSL = simsetup.stopConditionsSL;
				s = SimulationFactory.createSimulation(simulationSetup, HttpContext.Current.Server.MapPath("App_Data"));

				var g = s.getSimulationResultForSilverlight();

                Context.Session["simulation"] = s;
				//Application[token] = s;


				resultG.Vertices = new GraphElement[g.VertexCount];
				for (int i = 0; i < g.VertexCount; i++) {
					var v = g.Vertices.ElementAt(i);
					resultG.Vertices[i] = v;
				}


				resultG.Edges = new GraphEdge[g.Edges.Count()];
				for (int i = 0; i < g.Edges.Count(); i++) {
					var e = g.Edges.ElementAt(i);
					resultG.Edges[i] = new GraphEdge(e.Source, e.Target);
				}
				// resultG.Height = CountInfectious(s);
			}
			catch (Exception e) {
				//TODO: add handling
                Console.Write(e.StackTrace.ToString());
			}
			return resultG;
		}

        [WebMethod(EnableSession = true)]
        public void StartSimulationInBackGround(SimulationSetupSL simsetup, int numOfExperiments)
        {
            SimulationSetup simulationSetup = new SimulationSetup(simsetup.networkGraphML, simsetup.diseaseModelGraphML, simsetup.maxContactsPerStep, simsetup.minContactsPerStep);
            simulationSetup.networkGraph = simsetup.networkGraph;
            simulationSetup.stateChangePlansSL = simsetup.stateChangePlansSL;
            simulationSetup.stopConditionsSL = simsetup.stopConditionsSL;

            SimulationManager simManager = new SimulationManager(simulationSetup, numOfExperiments, HttpContext.Current.Server.MapPath("App_Data"));
            simManager.runSimulationAsync();
            Context.Session["AsyncSimManager"] = simManager;
        }

        [WebMethod(EnableSession = true)]
        public ExperimentState[] getExporimentState()
        {
            try
            {
                SimulationManager simManager = (SimulationManager)Context.Session["AsyncSimManager"];
                return simManager.getExperimentState();
            }
            catch (Exception e)
            { }
            
            return null;
        }

        [WebMethod(EnableSession = true)]
        public SimulationSimpleReport getAsyncSimulationReport()
        {
            try
            {
                SimulationManager simManager = (SimulationManager)Context.Session["AsyncSimManager"];
                return simManager.getSimulationReport();
            }
            catch (Exception e)
            { }

            return null;
        }

		[WebMethod(EnableSession=true)]
		public void AddStateChangePlan(StateChangePlanSL plan, String token) {
			Simulation s = null;

			if (Application[token] != null) {
				s = (Simulation)Application[token.ToString()];
			}

			StateChangePlan stateChangePlan = null;

			Type type = Type.GetType(plan.stateChangeStrategyName, true);
			object newInstance = Activator.CreateInstance(type);

			StateChangeStrategy strategy = (StateChangeStrategy)newInstance;
			if (plan.inPersents) {
				stateChangePlan = new PersentageStateChangePlan(plan.value, strategy, plan.applyTime);
			}
			else {
				stateChangePlan = new NumericalStateChangePlan(plan.value, strategy, plan.applyTime);
			}
			s.addStateChangePlan(stateChangePlan);
		}

		[WebMethod]
		public Graph CreateGraphWithDiseaseModelGraph(String graphML, DiseaseModelGraph stateMachineGraph, String token, int MaxSimStep) {
			Simulation s = null;

			//s = SimulationFactory.createSimulation(graphML, stateMachineGraphML, HttpContext.Current.Server.MapPath("App_Data"));//HttpContext.Current.Server.MapPath("App_Data/terror.graphml.xml"), HttpContext.Current.Server.MapPath("App_Data/sis.graphml.xml"));
			//s.addStopCondition(new MaxSimStepNumberStopCondition(MaxSimStep));
			//Application[token.ToString()] = s;

			//var g = s.getSimulationResultForSilverlight();

			Application[token] = s;

			Graph resultG = new Graph();
			//resultG.Vertices = new GraphElement[g.VertexCount];
			//for (int i = 0; i < g.VertexCount; i++)
			//{
			//    var v = g.Vertices.ElementAt(i);
			//    resultG.Vertices[i] = v;
			//}


			//resultG.Edges = new GraphEdge[g.Edges.Count()];
			//for (int i = 0; i < g.Edges.Count(); i++)
			//{
			//    var e = g.Edges.ElementAt(i);
			//    resultG.Edges[i] = new GraphEdge(e.Source, e.Target);
			//}

			return resultG;
		}

        [WebMethod(EnableSession = true)]
		public Graph NextStep(String token) {
            Simulation s = Context.Session["simulation"] as Simulation;

            if (s == null) return null;

			s.nextSimStep();
			var g = s.getSimulationResultForSilverlight();

			//Application[token] = s;

			Graph resultG = new Graph();
			resultG.Vertices = new GraphElement[g.VertexCount];
			for (int i = 0; i < g.VertexCount; i++) {
				var v = g.Vertices.ElementAt(i);
				resultG.Vertices[i] = v;
			}


			resultG.Edges = new GraphEdge[g.Edges.Count()];
			for (int i = 0; i < g.Edges.Count(); i++) {
				var e = g.Edges.ElementAt(i);
				resultG.Edges[i] = new GraphEdge(e.Source, e.Target);
			}
			resultG.Height = CountInfectious(s);
			return resultG;
		}

		[WebMethod]
		public String[] GetAvailableMethodsOfCentrality() {
			MethodInfo[] methods = typeof(ComplexNetCentralityLib.ComplexNetCentrality).GetMethods(BindingFlags.Static | BindingFlags.Public);
			List<String> toReturn = new List<string>();

			foreach (var item in methods) {
				ParameterInfo[] infos = item.GetParameters();
				if (infos.Count() == 1) {
					if (infos[0].Name == "socialNetwork")
						toReturn.Add(item.Name);
				}
			}

			return toReturn.ToArray();
		}

		[WebMethod]
		public Graph ComputeCentrality(String MethodName, Graph input) {
            UndirectedGraph<SocialNetworkNode, EdgeWithAttributes.EdgeWithAttributes<SocialNetworkNode>> graph = input.GetGraphFormSilverlight();
            AdjacencyGraph<IGraphMLComplexType, EdgeWithAttributes.EdgeWithAttributes<IGraphMLComplexType>> network = new AdjacencyGraph<IGraphMLComplexType, EdgeWithAttributes.EdgeWithAttributes<IGraphMLComplexType>>();
            foreach (EdgeWithAttributes.EdgeWithAttributes<SocialNetworkNode> edge in graph.Edges)
            {
                EdgeWithAttributes.EdgeWithAttributes<IGraphMLComplexType> e = new EdgeWithAttributes.EdgeWithAttributes<IGraphMLComplexType>(edge.Source, edge.Target);
                network.AddVerticesAndEdge(e);
            }

			Type complex = typeof(ComplexNetCentralityLib.ComplexNetCentrality);
			Graph centralityGraph = null;
			try {
				centralityGraph = (Graph)complex.GetMethod(MethodName).Invoke(null, new object[] { network });
				input.Merge(network);
			}
			catch (Exception e) {
				;
			}

			return input;
		}

        [WebMethod]
        public Graph ComputeCentralityFromGraphML(String MethodName, String graphML)
        {
            Graph resultG = new Graph();

            UndirectedGraph<SocialNetworkNode, EdgeWithAttributes.EdgeWithAttributes<SocialNetworkNode>> graph = GraphMLBuilder.Build<SocialNetworkNode>(graphML, HttpContext.Current.Server.MapPath("App_Data"));
            AdjacencyGraph<IGraphMLComplexType, EdgeWithAttributes.EdgeWithAttributes<IGraphMLComplexType>> network = new AdjacencyGraph<IGraphMLComplexType, EdgeWithAttributes.EdgeWithAttributes<IGraphMLComplexType>>();
            foreach (EdgeWithAttributes.EdgeWithAttributes<SocialNetworkNode> edge in graph.Edges)
            {
                EdgeWithAttributes.EdgeWithAttributes<IGraphMLComplexType> e = new EdgeWithAttributes.EdgeWithAttributes<IGraphMLComplexType>(edge.Source, edge.Target);
                network.AddVerticesAndEdge(e);
            }

            Type complex = typeof(ComplexNetCentralityLib.ComplexNetCentrality);
            complex.GetMethod(MethodName).Invoke(null, new object[] { network });

            var g = SocialNetworkNodeToGraphElement(graph);

            resultG.Vertices = new GraphElement[g.VertexCount];
            for (int i = 0; i < g.VertexCount; i++)
            {
                var v = g.Vertices.ElementAt(i);
                resultG.Vertices[i] = v;
            }


            resultG.Edges = new GraphEdge[g.Edges.Count()];
            for (int i = 0; i < g.Edges.Count(); i++)
            {
                var e = g.Edges.ElementAt(i);
                resultG.Edges[i] = new GraphEdge(e.Source, e.Target);
            }

            return resultG;
        }

        private UndirectedGraph<GraphElement, EdgeWithAttributes.EdgeWithAttributes<GraphElement>> SocialNetworkNodeToGraphElement(UndirectedGraph<SocialNetworkNode, EdgeWithAttributes.EdgeWithAttributes<SocialNetworkNode>> socialNetwork)
        {
            UndirectedGraph<GraphElement, EdgeWithAttributes.EdgeWithAttributes<GraphElement>> resultGraph = new UndirectedGraph<GraphElement, EdgeWithAttributes.EdgeWithAttributes<GraphElement>>();
            Dictionary<SocialNetworkNode, GraphElement> map = new Dictionary<SocialNetworkNode, GraphElement>();
            foreach (EdgeWithAttributes.EdgeWithAttributes<SocialNetworkNode> edge in socialNetwork.Edges)
            {

                GraphElement source = null;
                try
                {
                    source = map[edge.Source];
                }
                catch (KeyNotFoundException ex) { }

                GraphElement target = null;
                try
                {
                    target = map[edge.Target];
                }
                catch (KeyNotFoundException ex) { }

                if (source == null)
                {
                    source = new GraphElement();
                    map.Add(edge.Source, source);
                    source.x = edge.Source.x;
                    source.y = edge.Source.y;
                    source.Id = edge.Source.Id;
                    source.Height = edge.Source.Height;
                    source.Width = edge.Source.Width;
                    //source.Id = source.GetHashCode();
                    for (int i = 0; i < edge.Source.Keys.Count; i++)
                    {

                        var k = edge.Source.Keys.ElementAt(i);
                        PairKeyValue v = new PairKeyValue();
                        //if (k.Key != "stateName")
                        //{
                            v.Key = k.Key;
                            v.Value = k.Value;
                            source.Keys.Add(v);
                        /*}
                        else
                        {
                            v.Key = k.Key;
                            v.Value = edge.Source.state.stateNode.stateName;
                            source.Keys.Add(v);
                        }*/

                    }
                    resultGraph.AddVertex(source);
                }

                if (target == null)
                {
                    target = new GraphElement();
                    map.Add(edge.Target, target);
                    target.x = edge.Target.x;
                    target.y = edge.Target.y;
                    target.Id = edge.Target.Id;
                    target.Height = edge.Target.Height;
                    target.Width = edge.Target.Width;
                    for (int i = 0; i < edge.Target.Keys.Count; i++)
                    {
                        var k = edge.Target.Keys.ElementAt(i);
                        PairKeyValue v = new PairKeyValue();
                        //if (k.Key != "stateName")
                        //{
                            v.Key = k.Key;
                            v.Value = k.Value;
                            target.Keys.Add(v);
                        /*}
                        else
                        {
                            v.Key = k.Key;
                            v.Value = edge.Target.state.stateNode.stateName;
                            target.Keys.Add(v);
                        }*/
                    }
                    resultGraph.AddVertex(target);
                }

                EdgeWithAttributes.EdgeWithAttributes<GraphElement> e = new EdgeWithAttributes.EdgeWithAttributes<GraphElement>(source, target);
                resultGraph.AddEdge(e);
            }
            return resultGraph;
        }

        [WebMethod]
        public Graph GetGraphFromGraphML(String graphML)
        {
            Graph resultG = new Graph();

            UndirectedGraph<SocialNetworkNode, EdgeWithAttributes.EdgeWithAttributes<SocialNetworkNode>> graph = GraphMLBuilder.Build<SocialNetworkNode>(graphML, HttpContext.Current.Server.MapPath("App_Data"));

            var g = SocialNetworkNodeToGraphElement(graph);

            resultG.Vertices = new GraphElement[g.VertexCount];
            for (int i = 0; i < g.VertexCount; i++)
            {
                var v = g.Vertices.ElementAt(i);
                resultG.Vertices[i] = v;
            }


            resultG.Edges = new GraphEdge[g.Edges.Count()];
            for (int i = 0; i < g.Edges.Count(); i++)
            {
                var e = g.Edges.ElementAt(i);
                resultG.Edges[i] = new GraphEdge(e.Source, e.Target);
            }

            return resultG;
        }

		public int CountInfectious(Simulation s) {
			int count = 0;
			var v = s.getSimulationResult();

			foreach (var item in v.Vertices) {
				if (item.state.stateNode.stateName == "Infectious") {
					count++;
				}
			}

			return count;
		}

		[WebMethod]
		public string[] GetAvailableMethodsOfGenerator() {
			MethodInfo[] methods = typeof(ComplexNetGeneratorLib.ComplexNetGenerator).GetMethods();
			List<String> toReturn = new List<string>();

			foreach (var item in methods)
				if (item.Name.StartsWith("generate"))
					toReturn.Add(item.Name);

			return toReturn.ToArray();
		}

		[WebMethod]
		public string[] GetParametersFromMethod(string methodName) {
			MethodInfo method = typeof(ComplexNetGeneratorLib.ComplexNetGenerator).GetMethod(methodName);
			List<string> toReturn = new List<string>();

			ParameterInfo[] parameters = method.GetParameters();
			foreach (var p in parameters)
				toReturn.Add(p.Name);

			return toReturn.ToArray();
		}

		[WebMethod]
		public string[] GetParametersTypesFromMethod(string methodName) {
			MethodInfo method = typeof(ComplexNetGeneratorLib.ComplexNetGenerator).GetMethod(methodName);
			ParameterInfo[] parameters = method.GetParameters();
			string[] types = new string[parameters.Length];

			int i = 0;
			foreach (var item in parameters)
				types[i++] = item.ParameterType.ToString();

			return types;
		}

		/*[WebMethod]
		public Graph GenerateGraph(string methodName, object[] parameters)
		{
			MethodInfo method = typeof(ComplexNetGeneratorLib.ComplexNetGenerator).GetMethod(methodName);
			ComplexNetGenerator generator = new ComplexNetGenerator();

			ComplexNet net = method.Invoke(generator, parameters) as ComplexNet;

			return CreateGraphFromComplexNet(net);
		}*/

		[WebMethod]
		public Graph GenerateGraph(string methodName, object[] parameters) {
			MethodInfo method = typeof(ComplexNetGeneratorLib.ComplexNetGenerator).GetMethod(methodName);
			ComplexNetGenerator generator = new ComplexNetGenerator();

			ComplexNet net = method.Invoke(generator, parameters) as ComplexNet;

			Graph graph = CreateGraphFromComplexNet(net);

			DataBaseClassesDataContext db = new DataBaseClassesDataContext();
			var nodes = from n in db.Nodes
						select n;
			var nodesArray = nodes.ToArray();

			Random random = new Random();
			foreach (var vertex in graph.Vertices) {
				var n = nodesArray[random.Next() % nodesArray.Length];

				vertex.Keys.Add(new PairKeyValue("birthdate", n.birthdate.ToString()));
				vertex.Keys.Add(new PairKeyValue("country", n.country));
				vertex.Keys.Add(new PairKeyValue("image", n.image.ToString()));//zmiana spowodowana innym sposobem przechowywania zdjec
				vertex.Keys.Add(new PairKeyValue("latitude", n.latitude.ToString()));
				vertex.Keys.Add(new PairKeyValue("longitude", n.longitude.ToString()));
				vertex.Keys.Add(new PairKeyValue("name", n.name));
				vertex.Keys.Add(new PairKeyValue("postalcode", n.postalcode));
				vertex.Keys.Add(new PairKeyValue("street", n.street));
				vertex.Keys.Add(new PairKeyValue("surname", n.surname));
				vertex.Keys.Add(new PairKeyValue("town", n.town));
			}

			return graph;
		}

		private Graph CreateGraphFromComplexNet(ComplexNet net) {
			Graph g = new Graph();

			int i = 0;
			g.Vertices = new GraphElement[net.nodes.Count];
			foreach (ComplexNetNode node in net.nodes) {
				GraphElement v = new GraphElement() {
					Id = node.id.GetHashCode(),
					Keys = new List<PairKeyValue>()
				};
				v.Keys.Add(new PairKeyValue() {
					Key = v.Id + "_Key",
					Value = v.Id + "_Value"
				});
				g.Vertices[i++] = v;
			}

			i = 0;
			g.Edges = new GraphEdge[net.edges.Count];
			foreach (ComplexNetEdge edge in net.edges) {
				GraphEdge e = new GraphEdge() {
					Source = edge.source.id.GetHashCode(),
					Target = edge.target.id.GetHashCode()
				};
				g.Edges[i++] = e;
			}

			return g;
		}

    //    private String CreateGraphFCN(ComplexNet net)
    //    {
    //       String siec = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + Environment.NewLine +
    //"<graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://graphml.graphdrawing.org/xmlns " +
    //"http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd\">" + Environment.NewLine +
    //"  <key id=\"id\" for=\"node\" attr.name=\"id\" attr.type=\"string\" />" + Environment.NewLine +
    //"  <key id=\"name\" for=\"node\" attr.name=\"name\" attr.type=\"string\" />" + Environment.NewLine +
    //"  <key id=\"surname\" for=\"node\" attr.name=\"surname\" attr.type=\"string\" />" + Environment.NewLine +
    //"  <key id=\"birthdate\" for=\"node\" attr.name=\"birthdate\" attr.type=\"string\" />" + Environment.NewLine +
    //"  <key id=\"photo\" for=\"node\" attr.name=\"photo\" attr.type=\"string\" />" + Environment.NewLine +
    //"  <key id=\"location\" for=\"node\" attr.name=\"location\" attr.type=\"string\" />" + Environment.NewLine +
    //"  <key id=\"locationX\" for=\"node\" attr.name=\"locationX\" attr.type=\"string\" />" + Environment.NewLine +
    //"  <key id=\"locationY\" for=\"node\" attr.name=\"locationY\" attr.type=\"string\" />" + Environment.NewLine +
    //"  <key id=\"street\" for=\"node\" attr.name=\"street\" attr.type=\"string\" />" + Environment.NewLine +
    //"  <key id=\"town\" for=\"node\" attr.name=\"town\" attr.type=\"string\" />" + Environment.NewLine +
    //"  <key id=\"postalcode\" for=\"node\" attr.name=\"postalcode\" attr.type=\"string\" />" + Environment.NewLine +
    //"  <key id=\"country\" for=\"node\" attr.name=\"country\" attr.type=\"string\" />" + Environment.NewLine +
    //"  <key id=\"stateName\" for=\"node\" attr.name=\"stateName\" attr.type=\"string\" />" + Environment.NewLine +
    //" <graph edgedefault=\"undirected\">" + Environment.NewLine;

    //       String xmlNode;
    //       foreach (var node in net.nodes)
    //       {
    //           xmlNode = "<node id=\"" + Convert.ToString(node.id) + "\">" + Environment.NewLine;

    //           //TODO: jesli zostanie skonczony edytor
    //           //String key = "<data key=\"";
    //           //HashSet<String>.Enumerator e = node.attributes.GetEnumerator();
    //           //while (e.MoveNext())
    //           //{
    //           //    String attName = e.ToString();
    //           //    String att = e.Current;
    //           //}
    //           siec += xmlNode;
    //       }
    //       //<edge id="17" source="node24" target="node23" />
    //       String xmlEdge;
    //       foreach (var edge in net.edges)
    //       {
    //           xmlEdge = "<edge id=\"" + edge.id + "\" source=\"" + edge.source.id + "\" target=\"" + edge.target.id + "\" />" + Environment.NewLine; ;
    //           siec += xmlEdge;
    //       }

    //       return siec;
    //    }

		[WebMethod]
		public string[] GetDiseaseModelStateNames() {
			List<String> states = new List<string>();

			Type t = typeof(State);

			Assembly asm = t.Assembly;

			foreach (Type type in asm.GetTypes()) {
				if (type.BaseType == t) {
					String val = type.FullName;
					states.Add(val);
				}
			}

			return states.ToArray();
		}

        [WebMethod(EnableSession = true)]
		public void changeNodeState(String token, int nodeId, String newStateName) {
            Simulation s = Context.Session["simulation"] as Simulation;
            if (s == null) return;

			s.changeNodeState(nodeId, newStateName);
		}

        [WebMethod(EnableSession = true)]
		public void removeNode(String token, int nodeId) {
            Simulation s = Context.Session["simulation"] as Simulation;
            if (s == null) return;

			s.removeNode(nodeId);
		}

        [WebMethod(EnableSession = true)]
		public void removeEdge(String token, int sourceId, int targetId) {
            Simulation s = Context.Session["simulation"] as Simulation;
            if (s == null) return;

			s.removeEdge(sourceId, targetId);
		}

		[WebMethod]
		public string[] GetAvailableStateChangeStrategies() {
			List<String> strategies = new List<string>();
			Type t = typeof(EpidemicSimulator.strategies.StateChangeStrategy);
			Assembly asm = t.Assembly;
			foreach (Type type in asm.GetTypes()) {
				Type[] interfaces = type.GetInterfaces();
				foreach (Type interFace in interfaces) {

					if (interFace.FullName == t.FullName) {
						String val = type.Name;
						strategies.Add(val);
					}
				}
			}
			return strategies.ToArray();
		}

		[WebMethod]
		public string[] GetAvailableStopConditions() {
			List<String> stopConditions = new List<string>();
			Type t = typeof(EpidemicSimulator.stopconditions.StopCondition);
			Assembly asm = t.Assembly;
			foreach (Type type in asm.GetTypes()) {
				Type[] interfaces = type.GetInterfaces();
				foreach (Type interFace in interfaces) {

					if (interFace.FullName == t.FullName) {
						String val = type.Name;
						stopConditions.Add(val);
					}
				}
			}
			return stopConditions.ToArray();
		}

        [WebMethod(EnableSession = true)]
		public SimulationReport getSimulationReport(String token) {
            Simulation s = Context.Session["simulation"] as Simulation;
            if (s == null) return null;

            return s.getSimulationReport();
		}

		[WebMethod]
		public double[] GetGeoCode(string strAddress) {
			string strKey = "ABQIAAAAt21w088otvkx4dydGkSFzhTiWYdC4kK5HJo75hRqCbZEyPurWxRFE2iDTU5WiKeD_zuNhg5zVaDZbw";

			string sPath = "http://maps.google.com/maps/geo?q=" + strAddress + "&output=csv&key=" + strKey;


			WebClient client = new WebClient();

			string[] eResult = client.DownloadString(sPath).ToString().Split(',');

			string latitude = eResult.GetValue(2).ToString();
			string longitude = eResult.GetValue(3).ToString();

			return new double[] { Convert.ToDouble(latitude, NumberFormatInfo.InvariantInfo), Convert.ToDouble(longitude, NumberFormatInfo.InvariantInfo) };
		}

        [WebMethod]
        public string netToGraphml(string netName)
        {
            DataBaseClassesDataContext db = new DataBaseClassesDataContext();
            if (db.DatabaseExists() == false) return null;
            var net = (from n in db.Nets where n.netName == netName select n).Single();

			string graphml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\" "
				+ "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " + "xsi:schemaLocation=\"http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd\">\n";
			graphml += "\t<key id=\"id\" for=\"node\" attr.name=\"id\" attr.type=\"string\" />\n";
			graphml += "\t<key id=\"name\" for=\"node\" attr.name=\"name\" attr.type=\"string\" />\n";
			graphml += "\t<key id=\"surname\" for=\"node\" attr.name=\"surname\" attr.type=\"string\" />\n";
			graphml += "\t<key id=\"birthdate\" for=\"node\" attr.name=\"birthdate\" attr.type=\"string\" />\n";
            graphml += "\t<key id=\"photo\" for=\"node\" attr.name=\"photo\" attr.type=\"string\" />\n";
            graphml += "\t<key id=\"location\" for=\"node\" attr.name=\"location\" attr.type=\"string\" />\n";
            graphml += "\t<key id=\"locationX\" for=\"node\" attr.name=\"locationX\" attr.type=\"string\" />\n";
            graphml += "\t<key id=\"locationY\" for=\"node\" attr.name=\"locationY\" attr.type=\"string\" />\n";
			graphml += "\t<key id=\"street\" for=\"node\" attr.name=\"street\" attr.type=\"string\" />\n";
			graphml += "\t<key id=\"town\" for=\"node\" attr.name=\"town\" attr.type=\"string\" />\n";
			graphml += "\t<key id=\"postalcode\" for=\"node\" attr.name=\"postalcode\" attr.type=\"string\" />\n";
			graphml += "\t<key id=\"country\" for=\"node\" attr.name=\"country\" attr.type=\"string\" />\n";
			graphml += "\t<key id=\"stateName\" for=\"node\" attr.name=\"stateName\" attr.type=\"string\" />\n";
			graphml += "\t<graph edgedefault=\"undirected\">\n";

            var nodes = from n in db.Nodes select n;
            foreach(var n in nodes)
            {
				graphml += "\t\t<node id=\"node" + n.nodeID + "\">\n";
				graphml += "\t\t\t<data key=\"id\">n" + n.nodeID + "</data>\n";
				graphml += "\t\t\t<data key=\"name\">" + n.name + "</data>\n";
				graphml += "\t\t\t<data key=\"surname\">" + n.surname + "</data>\n";
				graphml += "\t\t\t<data key=\"birthdate\">" + n.birthdate + "</data>\n";
                graphml += "\t\t\t<data key=\"photo\">http://nosoifighters.studentlive.pl/GetImage.aspx?id=" + n.image + "</data>\n";
                graphml += "\t\t\t<data key=\"location\">" + n.country + "</data>\n";
                graphml += "\t\t\t<data key=\"locationX\">" + ((double)n.latitude).ToString(CultureInfo.CreateSpecificCulture("en-GB")) + "</data>\n";
                graphml += "\t\t\t<data key=\"locationY\">" + ((double)n.longitude).ToString(CultureInfo.CreateSpecificCulture("en-GB")) + "</data>\n";
				graphml += "\t\t\t<data key=\"street\">" + n.street + "</data>\n";
				graphml += "\t\t\t<data key=\"town\">" + n.town + "</data>\n";
				graphml += "\t\t\t<data key=\"postalcode\">" + n.postalcode + "</data>\n";
				graphml += "\t\t\t<data key=\"country\">" + n.country + "</data>\n";
				graphml += "\t\t\t<data key=\"stateName\">" + "Susceptible" + "</data>\n";
				graphml += "\t\t</node>\n";
            }

            var edges = (from e in db.Edges where e.netID == net.netID select e);
            foreach (var e in edges)
            {
				graphml += "\t\t<edge id=\"" + e.edgeID + "\" source=\"node" + e.leftNodeID + "\" target=\"node" + e.rightNodeID + "\" />\n";
            }

			graphml += "\t</graph>\n</graphml>\n";
            return graphml;
        }
	}
}
